import pandas as pd
import xmindparser
import re
import os
import json
from typing import List, Dict


class SimpleCSVXMindComparator:
    """简洁的CSV和XMind文件对比器"""

    def __init__(self, csv_file_path: str, xmind_file_path: str):
        self.csv_file_path = csv_file_path
        self.xmind_file_path = xmind_file_path

    def clean_text(self, text: str) -> str:
        """清理文本中的特殊符号"""
        if not text or pd.isna(text):
            return ""

        text = str(text)

        # 移除【】内容
        text = re.sub(r'【[^】]*】', '', text)

        # 移除常见特殊符号
        special_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|', '\n', '\r', '\t']
        for char in special_chars:
            text = text.replace(char, '')

        # 移除多余空格
        text = ' '.join(text.split())

        return text.strip()

    def extract_csv_names(self) -> List[str]:
        """从CSV文件提取name列"""
        try:
            df = pd.read_csv(self.csv_file_path, encoding='utf-8')

            if 'name' not in df.columns:
                print(f"错误: CSV文件中没有'name'列")
                print(f"可用列: {list(df.columns)}")
                return []

            # 提取并清理名称
            names = df['name'].dropna().astype(str).tolist()
            cleaned_names = []

            for name in names:
                clean_name = self.clean_text(name)
                if clean_name:
                    cleaned_names.append(clean_name)

            # 去重但保持顺序
            unique_names = []
            seen = set()
            for name in cleaned_names:
                if name not in seen:
                    seen.add(name)
                    unique_names.append(name)

            print(f"CSV文件提取到 {len(unique_names)} 个唯一名称")
            return unique_names

        except Exception as e:
            print(f"读取CSV文件失败: {e}")
            return []

    def extract_xmind_leaf_names(self) -> List[str]:
        """从XMind文件提取叶子节点名称"""
        try:
            data = xmindparser.xmind_to_dict(self.xmind_file_path)
            leaf_names = []

            # 遍历所有sheet
            for sheet in data:
                root_topic = sheet.get('topic', {})
                if root_topic:
                    self._find_leaf_nodes(root_topic, leaf_names)

            # 清理并去重
            cleaned_names = []
            for name in leaf_names:
                clean_name = self.clean_text(name)
                if clean_name:
                    cleaned_names.append(clean_name)

            # 去重但保持顺序
            unique_names = []
            seen = set()
            for name in cleaned_names:
                if name not in seen:
                    seen.add(name)
                    unique_names.append(name)

            print(f"XMind文件提取到 {len(unique_names)} 个唯一叶子节点")
            return unique_names

        except Exception as e:
            print(f"读取XMind文件失败: {e}")
            return []

    def _find_leaf_nodes(self, topic: dict, leaf_names: List[str]):
        """递归查找叶子节点"""
        title = topic.get('title', '')
        children = topic.get('topics', [])

        if not children:  # 叶子节点
            if title:
                leaf_names.append(title)
        else:  # 有子节点，递归处理
            for child in children:
                self._find_leaf_nodes(child, leaf_names)

    def find_xmind_missing_in_csv(self) -> List[str]:
        """找出XMind中有但CSV中没有的名称"""
        # 提取名称
        csv_names = self.extract_csv_names()
        xmind_names = self.extract_xmind_leaf_names()

        if not csv_names or not xmind_names:
            return []

        # 转换为集合进行比较
        csv_set = set(csv_names)
        xmind_set = set(xmind_names)

        # 找出XMind独有的名称
        xmind_only = list(xmind_set - csv_set)
        xmind_only.sort()  # 排序

        print(f"\n结果统计:")
        print(f"CSV名称总数: {len(csv_names)}")
        print(f"XMind叶子节点总数: {len(xmind_names)}")
        print(f"XMind独有名称数: {len(xmind_only)}")
        print(f"共同名称数: {len(csv_set & xmind_set)}")

        return xmind_only

    def save_results(self, xmind_only_names: List[str], output_file: str = "xmind_missing_in_csv.txt"):
        """保存结果到文件"""
        try:
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write("# XMind中有但CSV中没有的名称列表\n")
                f.write(f"# CSV文件: {os.path.basename(self.csv_file_path)}\n")
                f.write(f"# XMind文件: {os.path.basename(self.xmind_file_path)}\n")
                f.write(f"# 总计: {len(xmind_only_names)} 个\n\n")

                for i, name in enumerate(xmind_only_names, 1):
                    f.write(f"{i:3d}. {name}\n")

            print(f"结果已保存到: {output_file}")
            return True

        except Exception as e:
            print(f"保存文件失败: {e}")
            return False


def get_xmind_missing_names(csv_file: str, xmind_file: str) -> List[str]:
    """
    主要功能函数：获取XMind中有但CSV中没有的名称

    Args:
        csv_file: CSV文件路径
        xmind_file: XMind文件路径

    Returns:
        List[str]: XMind中有但CSV中没有的名称列表
    """
    # 检查文件是否存在
    if not os.path.exists(csv_file):
        print(f"错误: CSV文件不存在 - {csv_file}")
        return []

    if not os.path.exists(xmind_file):
        print(f"错误: XMind文件不存在 - {xmind_file}")
        return []

    print(f"开始比较文件...")
    print(f"CSV文件: {csv_file}")
    print(f"XMind文件: {xmind_file}")

    # 创建比较器
    comparator = SimpleCSVXMindComparator(csv_file, xmind_file)

    # 获取结果
    missing_names = comparator.find_xmind_missing_in_csv()

    if missing_names:
        # 保存结果
        comparator.save_results(missing_names)

        # 显示前20个结果
        print(f"\n前20个XMind独有的名称:")
        for i, name in enumerate(missing_names[:20], 1):
            print(f"{i:3d}. {name}")

        if len(missing_names) > 20:
            print(f"... 还有 {len(missing_names) - 20} 个名称")
    else:
        print("没有找到XMind独有的名称")

    return missing_names


def main():
    """主函数"""
    # 设置文件路径 - 请修改为实际路径
    csv_file_path = "D:\\project_file\\诊断式学习\\生产已有计划信息.csv"  # 修改为你的CSV文件路径
    xmind_file_path = "D:\\project_file\\诊断式学习\\全部.xmind"  # 修改为你的XMind文件路径

    # 检查文件路径是否需要修改
    if csv_file_path == "your_data.csv" or xmind_file_path == "your_file.xmind":
        print("请先修改文件路径:")
        print("1. 将 'your_data.csv' 替换为实际的CSV文件路径")
        print("2. 将 'your_file.xmind' 替换为实际的XMind文件路径")
        print("\n使用示例:")
        print('csv_file_path = "D:/data/my_data.csv"')
        print('xmind_file_path = "D:/data/my_mind.xmind"')
        return

    # 执行比较
    missing_names = get_xmind_missing_names(csv_file_path, xmind_file_path)

    if missing_names:
        print(f"\n✅ 成功找到 {len(missing_names)} 个XMind独有的名称")
        print("📄 完整结果已保存到 xmind_missing_in_csv.txt")
    else:
        print("❌ 没有找到XMind独有的名称或处理失败")


# 快速测试函数
def quick_test():
    """快速测试函数 - 修改这里的路径进行测试"""
    csv_path = "D:\\project_file\\诊断式学习\\生产已有计划信息0626.csv"  # 修改为你的CSV文件路径
    xmind_path = "D:\\project_file\\诊断式学习\\全部.xmind"  # 修改为你的XMind文件路径

    result = get_xmind_missing_names(csv_path, xmind_path)
    return result


if __name__ == "__main__":
    main()